package com.liqi.frame.comm.mybatisplus;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.liqi.frame.comm.base.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 类描述:查询条件构造器
 * 版本:3.0.1
 * 作者:snowing
 * 创建时间:2018年6月9日 下午13:01:38
 * 更新时间:2019-12-03 09:06:00
 */
@Getter
public class Assist {
	
	/*全局设置类字段*/
	// 全局设置，是否开启字段转换(默认开启，可被自定义设置覆盖)
	private static final boolean FIELD_CAST = true;
	// 数据库表字段是否使用驼峰(不使用驼峰则使用下划线)，开启字段转换生效
	private static final boolean CAMEL = false;
	
	/*常量类字段*/
	// 操作符
	public static final String AND_EQ = "andEq";
	public static final String OR_EQ = "orEq";
	public static final String AND_NEQ = "andNeq";
	public static final String OR_NEQ = "orNeq";
	public static final String AND_LT = "andLt";
	public static final String OR_LT = "orLt";
	public static final String AND_LTE = "andLte";
	public static final String OR_LTE = "orLte";
	public static final String AND_GT = "andGt";
	public static final String OR_GT = "orGt";
	public static final String AND_GTE = "andGte";
	public static final String OR_GTE = "orGte";
	public static final String AND_LLIKE = "andLike";
	public static final String AND_LIKE = "andLlike";
	public static final String OR_LIKE = "orLike";
	public static final String OR_LLIKE = "orLlike";
	
	// 自定义设置，构造方法中使用，是否开启字段转换(默认全局设置)
	private Boolean fieldCast;
	
	// 自定义设置，是否逻辑删除（默认为true）
	// Model设置了逻辑删除（delFlag=true），该字段可覆盖Model中的逻辑删除标识
	// Model设置了物理删除（delFlag=false），该字段无效
	@Setter
	private Boolean logicDel = true;
	
	// 数据范围过滤开关，默认打开，可临时关闭，仅在model中设置为数据过滤时有效
	@Setter
	private Boolean datascopeSwitch = true;
	
	// 累计的字段名
	private String sumColumnName;
	// 计算平均值的字段名
	private String avgColumnName;
	// 分组统计字段名
	private String groupBy;
	// 分组统计结果的key字段名
	private String groupKey;
	// 结果保留的小数位
	private Integer round;
	
	// 去重
	private String distinct;
	// 自定义排序
	private String order;
	// 数据分页开始行
	private Integer startRow;
	// 每次取多少行数据
	private Integer rowSize;
	// 设置自定义返回列
	private String resultColumn;
	// 条件集
	private List<WhereRequire<?>> require = null;
	// 排序集
	private List<WhereOrder> orderList = null;
	
	/**
	 * 条件类,require属性为列的条件,value为条件值,suffix为结尾
	 * 
	 * @author Mirren
	 */
	@Getter
	@Setter
	public static class WhereRequire<T> {
		private String require;// 条件语句
		private T value;// 单个值
		private Object[] values;// 多个值
		private String suffix;// 结束语句

		public WhereRequire(String require, T value) {
			super();
			this.require = require;
			this.value = value;
		}

		public WhereRequire(String require, T value, String suffix) {
			super();
			this.require = require;
			this.value = value;
			this.suffix = suffix;
		}

		public WhereRequire(String require, String suffix, Object... values) {
			super();
			this.require = require;
			this.values = values;
			this.suffix = suffix;
		}
	}

	/**
	 * 排序类用于排序column为列名,mode为排序方式,true=asc,false=desc
	 * 
	 * @author Mirren
	 *
	 */
	@Getter
	@Setter
	@AllArgsConstructor
	public static class WhereOrder {
		private String column;
		private boolean mode;
	}

	/**
	 * 添加查询条件,参数为Assist的内部类whereRequire,推荐使用Assist的静态条件方法添加条件;
	 * 
	 * @param whereRequire
	 *            示例:Assist.and_lt("id",10),...
	 */
	private Assist setRequires(WhereRequire<?> whereRequire) {
		if (this.require == null) {
			this.require = new ArrayList<WhereRequire<?>>();
		}
		if (null != whereRequire) {
			this.require.add(whereRequire);
		}
		return this;
	}

	/**
	 * 方法描述: 批量添加查询条件,参数为一个bean中的非空字段,推荐使用Assist的静态条件方法添加条件;
	 * @param bean 条件bean
	 * @param operator 操作符（枚举）
	 * @return
	 * 		Assist
	 * 作者:    snwoing
	 * 创建时间: 2019年2月19日 下午5:57:06
	 * 修改人:
	 * 修改时间:
	 * 修改内容:
	 * 修改次数: 0
	 */
	public Assist setRequires(BaseEntity bean, String operator) {
		bean.clearParams();
		Map<String, Object> map = BeanUtil.beanToMap(bean, false, true);
		return setRequires(map, operator);
	}

	/**
	 * 方法描述: 批量添加查询条件,参数为一个map中的非空字段,推荐使用Assist的静态条件方法添加条件;
	 * @param map 条件map
	 * @param operator 操作符（枚举）
	 * @return
	 * 		Assist
	 * 作者:    snwoing
	 * 创建时间: 2019年2月19日 下午5:57:06
	 * 修改人:
	 * 修改时间:
	 * 修改内容:
	 * 修改次数: 0
	 */
	public <T> Assist setRequires(Map<String, Object> map, String operator) {
		map.forEach((k, v) -> {
			this.setRequires(k, v, operator);
		});
		return this;
	}

	public <T> Assist setRequires(String name, T value, String operator) {
		switch (operator) {
		case AND_EQ :
			this.andEq(name, value);
			break;
		case OR_EQ :
			this.orEq(name, value);
			break;
		case AND_NEQ :
			this.andNeq(name, value);
			break;
		case OR_NEQ :
			this.orNeq(name, value);
			break;
		case AND_LT :
			this.andLt(name, value);
			break;
		case OR_LT :
			this.orLt(name, value);
			break;
		case AND_LTE :
			this.andLte(name, value);
			break;
		case OR_LTE :
			this.orLte(name, value);
			break;
		case AND_GT :
			this.andGt(name, value);
			break;
		case OR_GT :
			this.orGt(name, value);
			break;
		case AND_GTE :
			this.andGte(name, value);
			break;
		case OR_GTE :
			this.orGte(name, value);
			break;
		case AND_LIKE :
			this.andLike(name, value);
			break;
		case AND_LLIKE :
			this.andLlike(name, value);
			break;
		case OR_LIKE :
			this.orLike(name, value);
			break;
		case OR_LLIKE :
			this.orLlike(name, value);
			break;
		}
		return this;
	}

	/**
	 * 参数(列名)1 = 参数(条件)2 ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist andEq(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("and " + column + " = ", req);
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 = 参数(条件)2 ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist orEq(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("or " + column + " = ", req);
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 <T>(不等于) 参数(条件)2 ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist andNeq(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("and " + column + " <> ", req);
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 <>(不等于) 参数(条件)2 ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist orNeq(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("or " + column + " <> ", req);
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 < 参数(条件)2 ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist andLt(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("and " + column + " < ", req);
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 < 参数(条件)2 ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist orLt(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("or " + column + " < ", req);
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 <= 参数(条件)2 ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist andLte(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("and " + column + " <= ", req);
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 <= 参数(条件)2 ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist orLte(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("or " + column + " <= ", req);
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 > 参数(条件)2 ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist andGt(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("and " + column + " > ", req);
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 > 参数(条件)2 ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist orGt(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("or " + column + " > ", req);
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 >= 参数(条件)2 ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist andGte(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("and " + column + " >= ", req);
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 >= 参数(条件)2 ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist orGte(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("or " + column + " >= ", req);
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 like '参数(条件)2' ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist andLike(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("and " + column + " like concat('%',", req, ",'%')");
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 左侧like '参数(条件)2' ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist andLlike(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("and " + column + " like concat(", req, ",'%')");
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 like '参数(条件)2' ;如果表中存在相同列名,使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist orLike(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("or " + column + " like concat('%',", req, ",'%')");
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 参数(列名)1 左侧like '参数(条件)2' ;如果表中存在相同列名,使用表名.列名,如果不存在相同列名可以直接列名
	 *
	 * @param column
	 * @param req
	 * @return
	 */
	public <T> Assist orLlike(String column, T req) {
		if (!empty(req)) {
			column = fieldCast(column);
			WhereRequire<T> whereRequire = new Assist.WhereRequire<T>("or " + column + " like concat(", req, ",'%')");
			this.setRequires(whereRequire);
		}
		return this;
	}

	/**
	 * 新增加的in方法
	 *
	 * @param column
	 * @return
	 */
	public <T> Assist andInArray(String column, String[] values) {
		WhereRequire<T> whereRequire = null;
		column = fieldCast(column);
		if (null == values || values.length == 0) {
			whereRequire = new Assist.WhereRequire<T>("and (" + column + " is NULL or ", column + "= '')");
		} else {
			String joinStr = CollUtil.newHashSet(values).stream().filter(str -> StrUtil.isNotEmpty(str)).map(s -> "'" + s + "'").collect(Collectors.joining(", "));
			if (StrUtil.isNotEmpty(joinStr)) {
				String req = "(" + joinStr + ")";
				whereRequire = new Assist.WhereRequire<T>("and " + column + " in ", null,  req);
			} else {
				whereRequire = new Assist.WhereRequire<T>("and " + column + " in (\"", "\")");
			}
		}
		this.setRequires(whereRequire);
		return this;
	}

	/**
	 * 新增加的notin方法
	 *
	 * @param column
	 * @return
	 */
	public <T> Assist andNotinArray(String column, String[] values) {
		WhereRequire<T> whereRequire = null;
		column = fieldCast(column);
		if (null == values || values.length == 0) {
			whereRequire = new Assist.WhereRequire<T>("and (" + column + " is not NULL ", "and " + column + " <> '')");
		} else {
			String joinStr = CollUtil.newHashSet(values).stream().filter(str -> StrUtil.isNotEmpty(str)).map(s -> "'" + s + "'").collect(Collectors.joining(", "));
			if (StrUtil.isNotEmpty(joinStr)) {
				String req = "(" + joinStr + ")";
				whereRequire = new Assist.WhereRequire<T>("and " + column + " not in ", null,  req);
			} else {
				whereRequire = new Assist.WhereRequire<T>("and " + column + " not in (\"", "\")");
			}
		}
		this.setRequires(whereRequire);
		return this;
	}

	/**
	 * 新增加的in方法(自动去重)
	 *
	 * @param column
	 * @return
	 */
	public <T> Assist andInColl(String column, Collection<String> valuesColl) {
		WhereRequire<T> whereRequire = null;
		ArrayList<String> values = CollUtil.distinct(valuesColl);
		column = fieldCast(column);
		if (null == values || values.size() == 0) {
			whereRequire = new Assist.WhereRequire<T>("and (" + column + " is NULL or ", column + "= '')");
		} else {
			String joinStr = valuesColl.stream().distinct().filter(str -> StrUtil.isNotEmpty(str)).map(s -> "'" + s + "'").collect(Collectors.joining(", "));
			if (StrUtil.isNotEmpty(joinStr)) {
				String req = "(" + joinStr + ")";
				whereRequire = new Assist.WhereRequire<T>("and " + column + " in ", null, req);
			} else {
				whereRequire = new Assist.WhereRequire<T>("and " + column + " in (\"", "\")");
			}
		}
		this.setRequires(whereRequire);
		return this;
	}

	/**
	 * 新增加的notin方法(自动去重)
	 *
	 * @param column
	 * @return
	 */
	public <T> Assist andNotinColl(String column, Collection<String> valuesColl) {
		WhereRequire<T> whereRequire = null;
		ArrayList<String> values = CollUtil.distinct(valuesColl);
		column = fieldCast(column);
		if (null == values || values.size() == 0) {
			whereRequire = new Assist.WhereRequire<T>("and (" + column + " is not NULL ", "and " + column + " <> '')");
		} else {
			String joinStr = valuesColl.stream().distinct().filter(str -> StrUtil.isNotEmpty(str)).map(s -> "'" + s + "'").collect(Collectors.joining(", "));
			if (StrUtil.isNotEmpty(joinStr)) {
				String req = "(" + joinStr + ")";
				whereRequire = new Assist.WhereRequire<T>("and " + column + " not in ", null, req);
			} else {
				whereRequire = new Assist.WhereRequire<T>("and " + column + " not in (\"", "\")");
			}
		}
		this.setRequires(whereRequire);
		return this;
	}

	/**
	 * 新增加的in方法
	 *
	 * @param column
	 * @return
	 */
	public <T> Assist orInArray(String column, String[] values) {
		WhereRequire<T> whereRequire = null;
		column = fieldCast(column);
		if (null == values || values.length == 0) {
			whereRequire = new Assist.WhereRequire<T>("or (" + column + " is NULL or ", column + "= '')");
		} else {
			String joinStr = CollUtil.newHashSet(values).stream().filter(str -> StrUtil.isNotEmpty(str)).map(s -> "'" + s + "'").collect(Collectors.joining(", "));
			if (StrUtil.isNotEmpty(joinStr)) {
				String req = "(" + joinStr + ")";
				whereRequire = new Assist.WhereRequire<T>("or " + column + " in ", null, req);
			} else {
				whereRequire = new Assist.WhereRequire<T>("or " + column + " in (\"", "\")");
			}
		}
		this.setRequires(whereRequire);
		return this;
	}

	/**
	 * 新增加的in方法(自动去重)
	 *
	 * @param column
	 * @return
	 */
	public <T> Assist orInColl(String column, Collection<String> valuesColl) {
		WhereRequire<T> whereRequire = null;
		ArrayList<String> values = CollUtil.distinct(valuesColl);
		column = fieldCast(column);
		if (null == values || values.size() == 0) {
			whereRequire = new Assist.WhereRequire<T>("or (" + column + " is NULL or ", column + "= '')");
		} else {
			String joinStr = valuesColl.stream().distinct().filter(str -> StrUtil.isNotEmpty(str)).map(s -> "'" + s + "'").collect(Collectors.joining(", "));
			if (StrUtil.isNotEmpty(joinStr)) {
				String req = "(" + joinStr + ")";
				whereRequire = new Assist.WhereRequire<T>("or " + column + " in ", null, req);
			} else {
				whereRequire = new Assist.WhereRequire<T>("or " + column + " in (\"", "\")");
			}
		}
		this.setRequires(whereRequire);
		return this;
	}

	/**
	 * 新增加的isNull方法
	 *
	 * @param column
	 * @return
	 */
	public <T> Assist andNull(String column, boolean isNull) {
		WhereRequire<T> whereRequire = null;
		column = fieldCast(column);
		if (isNull) {
			whereRequire = new Assist.WhereRequire<T>("and (" + column + " is NULL or ", column + "= '')");
		} else {
			whereRequire = new Assist.WhereRequire<T>("and (" + column + " is not NULL ", "and " + column + " <> '')");
		}
		this.setRequires(whereRequire);
		return this;
	}

	/**
	 * 新增加的isNull方法
	 *
	 * @param column
	 * @return
	 */
	public <T> Assist orNull(String column, boolean isNull) {
		WhereRequire<T> whereRequire = null;
		column = fieldCast(column);
		if (isNull) {
			whereRequire = new Assist.WhereRequire<T>("or (" + column + " is NULL or ", column + "= '')");
		} else {
			whereRequire = new Assist.WhereRequire<T>("or (" + column + " is not NULL ", "and " + column + " <> '')");
		}
		this.setRequires(whereRequire);
		return this;
	}

	/**
	 * 自定义查询条件 :参数(自定义开头语句)1 参数(条件值)2 参数(自定义结尾语句)3
	 * ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名<br>
	 * 示例子查询:<br>
	 * 参数1= 列名 in (select 返回列名 from 表名 where 列名 = <br>
	 * 参数2= 123456<br>
	 * 参数3= ) <br>
	 * 假设有一张user表,里面有id列结果为:<br>
	 * select * from user where id in (select id from user where id=123456)<br>
	 * <b>需要特别注意的是,当where中不止一个条件的时候需要加上and或者or,根据自己的情况而定,多个值使用重载方法</b>
	 *
	 * @param prefix
	 * @param value
	 * @param suffix
	 * @return
	 */
	public <T> Assist customRequire(String prefix, T value, String suffix) {
		if (empty(prefix) && empty(value) && empty(suffix)) {
			return this;
		}
		WhereRequire<T> whereRequire = new Assist.WhereRequire<T>(prefix, value, suffix);
		this.setRequires(whereRequire);
		return this;
	}

	/**
	 * * 自定义查询条件 :参数(自定义开头语句)1 参数(条件值)2 参数(自定义结尾语句)3
	 * ;如果表中存在相同列名使用表名.列名,如果不存在相同列名可以直接列名<br>
	 * 示例: Assist.customRequire("select in (",")",1,2,3,4)
	 *
	 * @param prefix
	 * @param suffix
	 * @param value
	 * @return
	 */
	public <T> Assist customRequire(String prefix, String suffix, Object... value) {
		if (empty(prefix) && empty(value) && empty(suffix)) {
			return this;
		}
		WhereRequire<T> whereRequire = new Assist.WhereRequire<T>(prefix, suffix, value);
		this.setRequires(whereRequire);
		return this;
	}

	/**
	 * 方法描述: 创建排序条件并加入列表将(列名)参数1 按 参数2排序(true=ASC/false=DESC)
	 * 创建条件后需调用setOrder使条件生效。
	 * @param column 列名
	 * @param mode 排序类型,true=asc,false=desc
	 * @return
	 * 		Assist
	 * 作者:    snowing
	 * 创建时间: 2019年12月11日 上午9:52:40
	 * 版本：1.0
	 */
	public Assist order(String column, boolean mode) {
		column = fieldCast(column);
		if (null == orderList) {
			orderList = new ArrayList<>();
		}
		orderList.add(new WhereOrder(column, mode));
		return this;
	}

	/**
	 * 方法描述: 组装排序条件
	 * @return
	 * 		Assist
	 * 作者:    snowing
	 * 创建时间: 2019年12月11日 上午9:59:04
	 * 版本：1.0
	 */
	public Assist setOrder() {
		if (orderList == null || orderList.isEmpty()) {
			this.order = null;
			return this;
		}
		if (orderList.size() == 1) {
			WhereOrder whereOrder = orderList.get(0);
			if (whereOrder.isMode()) {
				this.order = "order By " + whereOrder.getColumn() + " asc";
			} else {
				this.order = "order By " + whereOrder.getColumn() + " desc";
			}
			return this;
		}
		StringBuffer sql = new StringBuffer("order By ");
		for (int i = 0; i < orderList.size(); i++) {
			WhereOrder whereOrder = orderList.get(i);
			if (i == 0) {
				if (whereOrder.isMode()) {
					sql.append(whereOrder.getColumn() + " asc");
				} else {
					sql.append(whereOrder.getColumn() + " desc");
				}
			} else {
				if (whereOrder.isMode()) {
					sql.append(", " + whereOrder.getColumn() + " asc");
				} else {
					sql.append(", " + whereOrder.getColumn() + " desc");
				}
			}
		}

		this.order = sql.toString();
		return this;
	}

	/**
	 * 设置是否去重
	 *
	 * @param distinct
	 */
	public Assist setDistinct(boolean distinct) {
		if (distinct) {
			this.distinct = "distinct";
			return this;
		}
		return this;
	}

	/**
	 * 设置从第几行开始取数据
	 *
	 * @param startRow
	 */
	public Assist setStartRow(Integer startRow) {
		this.startRow = startRow;
		return this;
	}

	/**
	 * 设置每次取多少行数据
	 *
	 * @param rowSize
	 */
	public Assist setRowSize(Integer rowSize) {
		this.rowSize = rowSize;
		return this;
	}

	/**
	 * 方法描述: 设置返回的列，驼峰命名并以英文逗号间隔，如：“id,colInt,colStr”;
	 * 如果有最大或最小条件，如：“id,max(colInt),colStr”,
	 * @param resultColumn
	 * @return
	 * 		Assist
	 * 作者:    snowing
	 * 创建时间: 2019年4月24日 上午11:15:19
	 */
	public Assist setResultColumn(String resultColumn) {
		// 处理字段拼接和转换
		if (null != resultColumn) {
			this.resultColumn = CollUtil.newHashSet(resultColumn.split(",")).stream()
					.filter(s -> s.trim().length() > 0)
					.map(s -> (this.fieldCast ? (fieldCast(s)) : s) + " as " + (s.contains("(") ? s.substring(s.indexOf("(") + 1, s.indexOf(")")) : s))
					.collect(Collectors.joining(", "));
		}
		return this;
	}

	/**
	 * 方法描述: 私有构造方法（默认开启字段转换）
	 * 作者:    snowing
	 * 创建时间: 2019年3月3日 下午12:16:04
	 * 修改人:
	 * 修改时间:
	 * 修改内容:
	 * 修改次数: 0
	 */
	private Assist() {
		super();
	}

	/**
	 * 方法描述: 获取对象实例（默认开启字段转换）
	 * @return
	 * 		Assist
	 * 作者:    snowing
	 * 创建时间: 2019年6月4日 上午9:09:15
	 * 版本：1.0
	 */
	public static Assist getInstance() {
		Assist assist = new Assist();
		assist.fieldCast = FIELD_CAST;
		return assist;
	}

	/**
	 * 方法描述: 获取对象实例（自定义是否开启字段转换）
	 * @param fieldCast 是否开启字段转换
	 * @return
	 * 		Assist
	 * 作者:    snowing
	 * 创建时间: 2019年6月4日 上午9:09:31
	 * 版本：1.0
	 */
	public static Assist getInstance(boolean fieldCast) {
		Assist assist = new Assist();
		assist.fieldCast = fieldCast;
		return assist;
	}

	/**
	 * 该构造方法用于使用Assist的静态条件方法,动态添加条件
	 *
	 * @param require
	 *            示例:Assist.lt("A.ID",10)...
	 */
	private Assist(WhereRequire<?>... require) {
		super();
		if (this.require == null) {
			this.require = new ArrayList<WhereRequire<?>>();
		}
		for (int i = 0; i < require.length; i++) {
			this.require.add(require[i]);
		}
	}
	
	/**
	 * 方法描述: 设置求和字段名
	 * @param sumColumnName
	 * @return
	 * 		Assist
	 * 作者:    snowing
	 * 创建时间: 2019年3月19日 下午1:24:24
	 * 修改人:
	 * 修改时间:
	 * 修改内容:
	 * 修改次数: 0
	 */
	public Assist setSumColumnName(String sumColumnName) {
		this.sumColumnName = fieldCast(sumColumnName);
		return this;
	}
	
	/**
	 * 方法描述: 设置分组统计(求和与计数)
	 * @param sumColumnName 统计字段名
	 * @param groupBy 分组字段名
	 * @param groupKey 统计结果的key
	 * @return
	 * 		Assist
	 * 作者:    snowing
	 * 创建时间: 2019年4月17日 下午10:07:36
	 */
	public Assist setGroupBySum(String sumColumnName, String groupBy, String groupKey) {
		this.sumColumnName = fieldCast(sumColumnName);
		this.groupBy = fieldCast(groupBy);
		this.groupKey = null == groupKey ? this.groupBy : fieldCast(groupKey);
		return this;
	}
	
	/**
	 * 方法描述: 设置分组统计(平均值)
	 * @param avgColumnName 计算平均值的列名
	 * @param groupBy 分组字段名(不分组传'id')
	 * @param round 结果保留的小数位
	 * @return
	 * 		Assist
	 * 作者:    snowing
	 * 创建时间: 2019年7月10日 上午10:48:27
	 * 版本：1.0
	 */
	public Assist setGroupByAvg(String avgColumnName, String groupBy, int round) {
		this.avgColumnName = fieldCast(avgColumnName);
		this.groupBy = fieldCast(groupBy);
		this.round = round < 0 ? 0 : round;
		return this;
	}
	
	/**
	 * 方法描述: 判断非集合对象是否为空
	 * @param value
	 * @return
	 * 		boolean
	 * 作者:    admin
	 * 创建时间: 2018年4月26日 下午3:17:54
	 * 修改人:
	 * 修改时间:
	 * 修改内容:
	 * 修改次数: 0
	 */
	private <T> boolean empty(T value) {
		if (null == value) {
			return true;
		} else if (value.getClass().toString().contains("String")) {
			if (((String) value).trim().length() == 0) {
				return true;
			} else if ("null".equals(((String) value).trim())) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 方法描述: 转换字段
	 * @param column
	 * @return
	 * 		String
	 * 作者:    snowing
	 * 创建时间: 2019年3月4日 下午3:28:24
	 * 修改人:
	 * 修改时间:
	 * 修改内容:
	 * 修改次数: 0
	 */
	public String fieldCast(String column) {
		if (StrUtil.isNotEmpty(column) && column.trim().length() > 0) {
			if (this.fieldCast) {
				if (CAMEL) {
					column = StrUtil.toCamelCase(column.trim());
				} else {
					column = StrUtil.toUnderlineCase(column.trim());
				}
			}
			return column.trim();
		}
		return null;
	}
	
}

